home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Design
/
WB Collection.iso
/
workbench werkzeuge
/
scherz programme
/
explode
/
explode.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-07
|
9KB
|
450 lines
/*
* explode.c - makes all Amiga windows "explode" when opening
*
* Bruno Costa - 30 Aug 89 - 31 Dec 89
*
* NOTE:
* This program is VERY sensitive to compiler environment.
* Compile under Lattice 5.0 with options -b0 -r0 -v.
*/
/* TODO:
- check for windows where 4*size(Window) > 5*size(Screen)
*/
#define DELAY 1
#define FASTDIV 0
#define DETACH 1
#define VERBOSE 1
#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfxmacros.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/layers.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include "intuition.lvo"
#include "common.h"
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
#if DETACH
long _stack = 2000;
char *_procname = "Window_Exploder";
long _priority = 5;
long _BackGroundIO = 1;
extern BPTR _Backstdout;
#else
BPTR _Backstdout;
#endif
/*
* Resident Amiga libraries
*/
struct Library *IntuitionBase;
struct Library *GfxBase;
struct Library *LayersBase;
/*
* CLI Messages
*/
#define BANNER "\x1b[33mExplode 1.2b\x1b[31m - \xa9 1989 by Bruno Costa\n"
#define USAGE "usage: \x1b[1mexplode\x1b[0m [-0..2] [-f] [-d] [-s] [-q] [<filename>]\n"
#define REMOVING "\x1b[1mExplode :\x1b[0m handler removed.\n"
/*
* pointer to old OpenWindow function
*/
void (* openWindow) (void);
/*
* external assembly routine interface
*/
extern void __far ExplodeWindow(void);
/*
* Patterns
*/
#define DASHED 0x5555
#define FULL 0xffff
/*
* These are globals just for the sake of efficiency
* (avoids stack parameter passing).
*/
static struct Screen scr;
static struct RastPort *rp;
static int x0, y0, x, y, w, h;
static int xi, yi, xf, yf;
/*
* Extended message port - contains global data
*/
#define PORTNAME "Explode_port"
struct ExtMsgPort {
struct MsgPort theport;
unsigned long int tagcode;
char tag[TAGSIZE]; /* tag to mark start of data */
int timedelay, pattern, nsteps;
struct {
struct {
int x, y;
} topleft, botright;
} step[MAXSTEPS];
};
static struct ExtMsgPort myport = {
{NULL},
TAG_CODE,
TAG_ID,
DEFDELAY, DEFPAT, 21,
{
{ 0, 0, 0, 0 }, /* left, top, right, bottom */
{ 135, -22, 135, -22 },
{ 265, -30, 265, -30 },
{ 389, -25, 389, -25 },
{ 506, -6, 506, -6 },
{ 615, 23, 615, 23 },
{ 717, 62, 717, 62 },
{ 811, 111, 811, 111 },
{ 895, 168, 895, 168 },
{ 971, 231, 971, 231 },
{ 1036, 300, 1036, 300 },
{ 1090, 373, 1090, 373 },
{ 1134, 449, 1134, 449 },
{ 1166, 527, 1166, 527 },
{ 1186, 605, 1186, 605 },
{ 1194, 683, 1194, 683 },
{ 1188, 759, 1188, 759 },
{ 1169, 833, 1169, 833 },
{ 1135, 902, 1135, 902 },
{ 1087, 966, 1087, 966 },
{ 1024, 1024, 1024, 1024 } /* 21th entry */
}
};
/*
* The points above were generated using an HP-28S and a bezier curve
* plotting program. The curve was broken in 20 line segments and the
* control points were: (0, 0) ; (922, -205) ; (1587, 665) ; (1024, 1024)
*/
#define xclip(x) (MAX(0, MIN(x, scr.Width - 1)))
#define yclip(y) (MAX(0, MIN(y, scr.Height - 1)))
/*
* Draws a line performing a simple clipping that only works for
* horizontal or vertical lines (the ones I draw).
*/
void line (int x1, int y1, int x2, int y2)
{
int x1c, y1c, x2c, y2c;
x1c = xclip (x1);
y1c = yclip (y1);
x2c = xclip (x2);
y2c = yclip (y2);
if ( ((x1c == x1) && (y1c == y1)) || ((x2c == x2) && (y2c == y2)) )
{
Move (rp, x1c, y1c);
Draw (rp, x2c, y2c);
}
}
/*
* Draws the outline from (xi,yi)-(xf,yf)
*/
void DrawOutline (void)
{
line (xi, yi, xf, yi);
line (xf, yi, xf, yf);
line (xf, yf, xi, yf);
line (xi, yf, xi, yi);
}
/*
* Does the animation of the outline along the path
*/
void MoveOutline (void)
{
register int i;
int dxi, dyi, dxf, dyf;
int nxi, nyi, nxf, nyf;
dxi = x - x0;
dyi = y - y0;
dxf = (x + w - 1) - x0;
dyf = (y + h - 1) - y0;
for (i = 0; i < myport.nsteps; i++)
{
#if FASTDIV
/*
* "Divides" faster by shifting (does it work for negative numbers ?)
*/
nxi = x0 + ((myport.step[i].topleft.x * dxi) >> 10);
nyi = y0 + ((myport.step[i].topleft.y * dyi) >> 10);
nxf = x0 + ((myport.step[i].botright.x * dxf) >> 10);
nyf = y0 + ((myport.step[i].botright.y * dyf) >> 10);
#else
nxi = x0 + ((myport.step[i].topleft.x * dxi) / 1024);
nyi = y0 + ((myport.step[i].topleft.y * dyi) / 1024);
nxf = x0 + ((myport.step[i].botright.x * dxf) / 1024);
nyf = y0 + ((myport.step[i].botright.y * dyf) / 1024);
#endif
if (i)
DrawOutline (); /* erases outline */
xi = nxi;
yi = nyi;
xf = nxf;
yf = nyf;
DrawOutline (); /* draws outline */
#if DELAY
Delay (myport.timedelay); /* quick pause */
#endif
}
DrawOutline ();
}
/*
* C routine that does the real explosion
*/
void __far DoExplode(struct NewWindow *nw)
{
if (GetScreenData (&scr, sizeof(struct Screen), nw->Type, nw->Screen))
{
/*
* I am working on a copy of the RastPort, so I won't care to restore
* old values like drawing modes and current position.
*/
rp = &scr.RastPort;
SetDrMd (rp, COMPLEMENT | JAM1);
SetDrPt (rp, myport.pattern);
x0 = xclip (scr.MouseX); /* assure that coordinates are */
y0 = yclip (scr.MouseY); /* inside this screen. */
x = nw->LeftEdge;
y = nw->TopEdge;
w = nw->Width;
h = nw->Height;
LockLayers (&scr.LayerInfo);
MoveOutline (); /* Now move window along the path */
UnlockLayers (&scr.LayerInfo);
}
}
#if VERBOSE
/*
* window text shadows
*/
static struct IntuiText TextS3 = {
2,0,JAM1,
26,30,
NULL,
"(September, 26th 1989)",
NULL
};
static struct IntuiText TextS2 = {
2,0,JAM1,
25,19,
NULL,
"written by Bruno Costa",
&TextS3
};
static struct IntuiText TextS1 = {
2,0,JAM1,
71,6,
NULL,
"Explode 1.2",
&TextS2
};
#define windshadow TextS1
static struct IntuiText IText3 = {
1,0,JAM1,
26,30,
NULL,
"(September, 26th 1989)",
NULL
};
static struct IntuiText IText2 = {
1,0,JAM1,
25,19,
NULL,
"written by Bruno Costa",
&IText3
};
static struct IntuiText IText1 = {
3,0,JAM1,
71,6,
NULL,
"Explode 1.2",
&IText2
};
#define windtext IText1
static struct NewWindow wind = {
207, 71, 227, 47, 0, 1, NULL,
SIMPLE_REFRESH + RMBTRAP + NOCAREREFRESH,
NULL, NULL, NULL, NULL, NULL,
0, 0, 0, 0, WBENCHSCREEN
};
#endif
void usage (void) /* dead end */
{
Write (_Backstdout, USAGE, sizeof(USAGE));
#if DETACH
Close (_Backstdout);
#endif
exit (5);
}
main(int argc, char *argv[])
{
int i, removed, verbose = TRUE, stay = FALSE;
struct Window *w;
struct ExtMsgPort *port;
#if !DETACH
_Backstdout = Output();
#endif
port = (struct ExtMsgPort *) FindPort (PORTNAME);
if (!port)
{
port = &myport;
stay = TRUE;
}
if (_Backstdout && argc)
{
if (stay)
Write (_Backstdout, BANNER, sizeof(BANNER));
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
{ /* argument is an option */
if (argv[i][1] >= '0' && argv[i][1] <= '2')
port->timedelay = argv[i][1] - '0';
else if (argv[i][1] == 'f')
port->pattern = FULL;
else if (argv[i][1] == 'd')
port->pattern = DASHED;
else if (argv[i][1] == 's')
verbose = FALSE;
else if (argv[i][1] == 'q')
{
if (stay)
stay = FALSE;
else
{
Signal (port->theport.mp_SigTask, 1L << port->theport.mp_SigBit);
port = &myport;
}
Write (_Backstdout, REMOVING, sizeof(REMOVING));
}
else
usage();
}
else
{ /* argument is a filename */
usage();
}
}
#if DETACH
Close (_Backstdout);
#endif
}
if (stay)
{
/* create port */
myport.theport.mp_Node.ln_Name = PORTNAME;
myport.theport.mp_Node.ln_Pri = 0;
myport.theport.mp_Node.ln_Type = NT_MSGPORT;
myport.theport.mp_Flags = PA_SIGNAL;
myport.theport.mp_SigBit = AllocSignal (-1);
myport.theport.mp_SigTask = FindTask (NULL);
AddPort (&myport.theport);
port = &myport;
}
else
goto final;
GfxBase = OpenLibrary ("graphics.library", 0);
LayersBase = OpenLibrary ("layers.library", 0);
IntuitionBase = OpenLibrary ("intuition.library", 0);
openWindow = SetFunction (IntuitionBase, _LVOOpenWindow, ExplodeWindow);
#if VERBOSE
if (verbose)
{
w = OpenWindow (&wind); /* notify that handler is installed */
if (w)
{
PrintIText (w->RPort, &windshadow, 2, 1);
PrintIText (w->RPort, &windtext, 0, 0);
Delay (200);
CloseWindow (w);
}
}
#endif
do
{
Wait (1L << port->theport.mp_SigBit); /* wait for termination signal */
Forbid ();
if (SetFunction (IntuitionBase, _LVOOpenWindow, openWindow) != ExplodeWindow)
{
/*
* Someone has interposed a handler after me. My handler can't be
* removed: otherwise the system will crash after the other handler
* removes itself.
*/
(void) SetFunction (IntuitionBase, _LVOOpenWindow, ExplodeWindow);
removed = FALSE;
}
else
removed = TRUE;
Permit();
} while (!removed);
CloseLibrary (IntuitionBase);
CloseLibrary (LayersBase);
CloseLibrary (GfxBase);
/* Delete port */
RemPort (&port->theport);
FreeSignal (port->theport.mp_SigBit);
final:
exit (0);
}